use rand::Rng;
use std::cmp::Ordering;
use std::io;
use std::{thread, time};

//////////////////////////////////////////
//         struct
//////////////////////////////////////////
// 增加属性来派生 Debug trait
#[derive(Debug)]
struct Rect {
    width: u32,
    height: u32,
}

// 在一个 impl 块中，Self 类型是 impl 块的类型的别名。方法的第一个参数必须有一个名为 self 的Self 类型的参数, 第二个之后的参数按需
impl Rect {
    // 关联函数
    // 我们可以定义不以 self 为第一参数的关联函数（因此不是方法），因为它们并不作用于一个结构体的实例。
    // 使用结构体名和 :: 语法来调用这个关联函数：比如 let sq = Rect::new(3, 6);
    fn new(width: u32, height: u32) -> Rect {
        Rect {
            width: width,
            height: height
        }
    }

    // 关联函数
    fn can_hold(&self, ract: &Rect) -> bool {
        self.area() > ract.area()
    }

    // 关联函数
    // 在 self 前面使用 & 来表示这个方法借用了 Self 实例
    // 因为不需要获取所有权，只希望能够读取结构体中的数据，而不是写入。
    // 如果想要在方法中改变调用方法的实例，需要将第一个参数改为 &mut self。
    // 使用方法替代函数，其主要好处在于组织性。我们将某个类型实例能做的所有事情都一起放入 impl 块中，而不是让将来的用户在我们的库中到处寻找 Rectangle 的功能。
    fn area(&self) -> u32 {
        self.width * self.height
    }
}


pub fn method_conf() {
    println!("#################################");
    println!("#################################");
    println!("method_conf.");

    // 编写一个计算长方形面积的程序
    areaComp();

    let rect1 = Rect::new(30, 50);
    let rect2 = Rect::new(10, 40);
    let rect3 = Rect::new(60, 45);

    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}

fn areaComp(){
    // let rectangle = Rect {
    //     width: 30,
    //     height: 50,
    // };
    let rectangle = &Rect::new(30, 50);

    println!(
        "The area of the rectangle is {} square pixels.",
        rectangle.area()
    );
}

